import UIKit
extension MarkdownTheme {
    public struct BaseConfig {
        public let font: UIFont
        public let textColor: UIColor
        public let backgroundColor: UIColor
        public let lineSpacing: CGFloat
        public let lineHeightMultiple: CGFloat
        public let paragraphSpacing: CGFloat
        public let spacing: CGFloat
        public let separatorColor: UIColor
        
        public init(
            font: UIFont = .systemFont(ofSize: 16),
            textColor: UIColor = .label,
            backgroundColor: UIColor = .systemBackground,
            lineSpacing: CGFloat = 4,
            lineHeightMultiple: CGFloat = 1.2,
            paragraphSpacing: CGFloat = 12,
            spacing: CGFloat = 8,
            separatorColor: UIColor = .separator
        ) {
            self.font = font
            self.textColor = textColor
            self.backgroundColor = backgroundColor
            self.lineSpacing = lineSpacing
            self.lineHeightMultiple = lineHeightMultiple
            self.paragraphSpacing = paragraphSpacing
            self.spacing = spacing
            self.separatorColor = separatorColor
        }
    }

    public struct TextConfig {
        public let font: UIFont
        public let boldFont: UIFont
        public let italicFont: UIFont
        public let textColor: UIColor
        public let backgroundColor: UIColor
        public let lineSpacing: CGFloat
        public let lineHeightMultiple: CGFloat
        
        public init(
            font: UIFont = .systemFont(ofSize: 16),
            boldFont: UIFont = .boldSystemFont(ofSize: 16),
            italicFont: UIFont = .italicSystemFont(ofSize: 16),
            textColor: UIColor = .label,
            backgroundColor: UIColor = .clear,
            lineSpacing: CGFloat = 4,
            lineHeightMultiple: CGFloat = 1.2
        ) {
            self.font = font
            self.boldFont = boldFont
            self.italicFont = italicFont
            self.textColor = textColor
            self.backgroundColor = backgroundColor
            self.lineSpacing = lineSpacing
            self.lineHeightMultiple = lineHeightMultiple
        }
    }

    public struct HeadingConfig {
        public struct HeadingStyle {
            public let font: UIFont
            public let textColor: UIColor
            public let backgroundColor: UIColor
            public let lineSpacing: CGFloat
            public let paragraphSpacing: CGFloat
            public let lineHeightMultiple: CGFloat
            
            public init(
                font: UIFont,
                textColor: UIColor = .label,
                backgroundColor: UIColor = .clear,
                lineSpacing: CGFloat = 8,
                paragraphSpacing: CGFloat = 16,
                lineHeightMultiple: CGFloat = 1.2
            ) {
                self.font = font
                self.textColor = textColor
                self.backgroundColor = backgroundColor
                self.lineSpacing = lineSpacing
                self.paragraphSpacing = paragraphSpacing
                self.lineHeightMultiple = lineHeightMultiple
            }
            
            public static let h1 = HeadingStyle(
                font: .boldSystemFont(ofSize: 28),
                paragraphSpacing: 20
            )
            
            public static let h2 = HeadingStyle(
                font: .boldSystemFont(ofSize: 24),
                paragraphSpacing: 18
            )
            
            public static let h3 = HeadingStyle(
                font: .boldSystemFont(ofSize: 20),
                paragraphSpacing: 16
            )
            
            public static let h4 = HeadingStyle(
                font: .boldSystemFont(ofSize: 18),
                paragraphSpacing: 14
            )
            
            public static let h5 = HeadingStyle(
                font: .boldSystemFont(ofSize: 16),
                paragraphSpacing: 12
            )
            
            public static let h6 = HeadingStyle(
                font: .boldSystemFont(ofSize: 14),
                paragraphSpacing: 10
            )
            
            public static let darkH1 = HeadingStyle(
                font: .boldSystemFont(ofSize: 28),
                textColor: .white,
                paragraphSpacing: 20
            )
            
            public static let darkH2 = HeadingStyle(
                font: .boldSystemFont(ofSize: 24),
                textColor: .white,
                paragraphSpacing: 18
            )
            
            public static let darkH3 = HeadingStyle(
                font: .boldSystemFont(ofSize: 20),
                textColor: .white,
                paragraphSpacing: 16
            )
            
            public static let darkH4 = HeadingStyle(
                font: .boldSystemFont(ofSize: 18),
                textColor: .white,
                paragraphSpacing: 14
            )
            
            public static let darkH5 = HeadingStyle(
                font: .boldSystemFont(ofSize: 16),
                textColor: .white,
                paragraphSpacing: 12
            )
            
            public static let darkH6 = HeadingStyle(
                font: .boldSystemFont(ofSize: 14),
                textColor: .white,
                paragraphSpacing: 10
            )
        }
        
        public let h1: HeadingStyle
        public let h2: HeadingStyle
        public let h3: HeadingStyle
        public let h4: HeadingStyle
        public let h5: HeadingStyle
        public let h6: HeadingStyle
        
        public init(
            h1: HeadingStyle = .h1,
            h2: HeadingStyle = .h2,
            h3: HeadingStyle = .h3,
            h4: HeadingStyle = .h4,
            h5: HeadingStyle = .h5,
            h6: HeadingStyle = .h6
        ) {
            self.h1 = h1
            self.h2 = h2
            self.h3 = h3
            self.h4 = h4
            self.h5 = h5
            self.h6 = h6
        }
        
        public static let light = HeadingConfig()
        
        public static let dark = HeadingConfig(
            h1: .darkH1,
            h2: .darkH2,
            h3: .darkH3,
            h4: .darkH4,
            h5: .darkH5,
            h6: .darkH6
        )
    }

    public struct CodeConfig {
        public let font: UIFont
        public let inlineFont: UIFont
        public let textColor: UIColor
        public let backgroundColor: UIColor
        public let inlineTextColor: UIColor
        public let inlineBackgroundColor: UIColor
        public let cornerRadius: CGFloat
        public let borderWidth: CGFloat
        public let borderColor: UIColor
        public let insets: UIEdgeInsets
        public let codeBlockPadding: UIEdgeInsets
        
        public init(
            font: UIFont = .monospacedSystemFont(ofSize: 14, weight: .regular),
            inlineFont: UIFont = .monospacedSystemFont(ofSize: 14, weight: .regular),
            textColor: UIColor = .systemPink,
            backgroundColor: UIColor = .systemGray6,
            inlineTextColor: UIColor = .systemPink,
            inlineBackgroundColor: UIColor = .systemGray6,
            cornerRadius: CGFloat = 8,
            borderWidth: CGFloat = 1,
            borderColor: UIColor = .separator,
            insets: UIEdgeInsets = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16),
            codeBlockPadding: UIEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
        ) {
            self.font = font
            self.inlineFont = inlineFont
            self.textColor = textColor
            self.backgroundColor = backgroundColor
            self.inlineTextColor = inlineTextColor
            self.inlineBackgroundColor = inlineBackgroundColor
            self.cornerRadius = cornerRadius
            self.borderWidth = borderWidth
            self.borderColor = borderColor
            self.insets = insets
            self.codeBlockPadding = codeBlockPadding
        }
    }

    public struct QuoteConfig {
        public let font: UIFont
        public let textColor: UIColor
        public let backgroundColor: UIColor
        public let borderColor: UIColor
        public let borderWidth: CGFloat
        public let insets: UIEdgeInsets
        
        public init(
            font: UIFont = .systemFont(ofSize: 16),
            textColor: UIColor = .secondaryLabel,
            backgroundColor: UIColor = .systemGray6,
            borderColor: UIColor = .systemBlue,
            borderWidth: CGFloat = 4,
            insets: UIEdgeInsets = UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16)
        ) {
            self.font = font
            self.textColor = textColor
            self.backgroundColor = backgroundColor
            self.borderColor = borderColor
            self.borderWidth = borderWidth
            self.insets = insets
        }
    }

    public struct LinkConfig {
        public struct ColorSet {
            public let textColor: UIColor
            public let backgroundColor: UIColor
            public let underlineColor: UIColor
            
            public init(
                textColor: UIColor,
                backgroundColor: UIColor,
                underlineColor: UIColor
            ) {
                self.textColor = textColor
                self.backgroundColor = backgroundColor
                self.underlineColor = underlineColor
            }
            
            public static let `default` = ColorSet(
                textColor: .systemBlue,
                backgroundColor: .clear,
                underlineColor: .systemBlue
            )
            
            public static let external = ColorSet(
                textColor: .systemBlue,
                backgroundColor: UIColor.systemBlue.withAlphaComponent(0.1),
                underlineColor: .systemBlue
            )
            
            public static let `internal` = ColorSet(
                textColor: .systemGreen,
                backgroundColor: UIColor.systemGreen.withAlphaComponent(0.1),
                underlineColor: .systemGreen
            )
            
            public static let custom = ColorSet(
                textColor: .systemPurple,
                backgroundColor: UIColor.systemPurple.withAlphaComponent(0.1),
                underlineColor: .systemPurple
            )
            
            public static let darkDefault = ColorSet(
                textColor: UIColor(red: 0.4, green: 0.6, blue: 1.0, alpha: 1.0),
                backgroundColor: .clear,
                underlineColor: UIColor(red: 0.4, green: 0.6, blue: 1.0, alpha: 1.0)
            )
            
            public static let darkExternal = ColorSet(
                textColor: UIColor(red: 0.4, green: 0.6, blue: 1.0, alpha: 1.0),
                backgroundColor: UIColor(red: 0.4, green: 0.6, blue: 1.0, alpha: 0.1),
                underlineColor: UIColor(red: 0.4, green: 0.6, blue: 1.0, alpha: 1.0)
            )
            
            public static let darkInternal = ColorSet(
                textColor: UIColor(red: 0.4, green: 0.8, blue: 0.4, alpha: 1.0),
                backgroundColor: UIColor(red: 0.4, green: 0.8, blue: 0.4, alpha: 0.1),
                underlineColor: UIColor(red: 0.4, green: 0.8, blue: 0.4, alpha: 1.0)
            )
            
            public static let darkCustom = ColorSet(
                textColor: UIColor(red: 0.8, green: 0.4, blue: 0.8, alpha: 1.0),
                backgroundColor: UIColor(red: 0.8, green: 0.4, blue: 0.8, alpha: 0.1),
                underlineColor: UIColor(red: 0.8, green: 0.4, blue: 0.8, alpha: 1.0)
            )
        }
        
        public let defaultColors: ColorSet
        public let externalColors: ColorSet
        public let internalColors: ColorSet
        public let customColors: ColorSet
        
        public init(
            defaultColors: ColorSet = .default,
            externalColors: ColorSet = .external,
            internalColors: ColorSet = .internal,
            customColors: ColorSet = .custom
        ) {
            self.defaultColors = defaultColors
            self.externalColors = externalColors
            self.internalColors = internalColors
            self.customColors = customColors
        }
        
        public static let light = LinkConfig()
        
        public static let dark = LinkConfig(
            defaultColors: .darkDefault,
            externalColors: .darkExternal,
            internalColors: .darkInternal,
            customColors: .darkCustom
        )
    }

    public struct ListConfig {
        public let font: UIFont
        public let textColor: UIColor
        public let backgroundColor: UIColor
        public let bulletColor: UIColor
        public let bulletFont: UIFont
        public let indentationWidth: CGFloat
        public let bulletWidth: CGFloat
        public let lineSpacing: CGFloat
        public let itemSpacing: CGFloat
        
        public let taskListCheckboxSize: CGFloat
        public let taskListCheckboxTintColor: UIColor
        public let taskListTextColor: UIColor
        public let taskListCompletedTextColor: UIColor
        public let taskListStrikethrough: Bool
        public let taskListIndentation: CGFloat
        public let taskListSpacing: CGFloat
        
        public init(
            font: UIFont = .systemFont(ofSize: 16),
            textColor: UIColor = .label,
            backgroundColor: UIColor = .clear,
            bulletColor: UIColor = .label,
            bulletFont: UIFont = .systemFont(ofSize: 16),
            indentationWidth: CGFloat = 20,
            bulletWidth: CGFloat = 20,
            lineSpacing: CGFloat = 4,
            itemSpacing: CGFloat = 8,
            
            taskListCheckboxSize: CGFloat = 22,
            taskListCheckboxTintColor: UIColor = .systemBlue,
            taskListTextColor: UIColor = .label,
            taskListCompletedTextColor: UIColor = .secondaryLabel,
            taskListStrikethrough: Bool = true,
            taskListIndentation: CGFloat = 8,
            taskListSpacing: CGFloat = 12
        ) {
            self.font = font
            self.textColor = textColor
            self.backgroundColor = backgroundColor
            self.bulletColor = bulletColor
            self.bulletFont = bulletFont
            self.indentationWidth = indentationWidth
            self.bulletWidth = bulletWidth
            self.lineSpacing = lineSpacing
            self.itemSpacing = itemSpacing
            
            self.taskListCheckboxSize = taskListCheckboxSize
            self.taskListCheckboxTintColor = taskListCheckboxTintColor
            self.taskListTextColor = taskListTextColor
            self.taskListCompletedTextColor = taskListCompletedTextColor
            self.taskListStrikethrough = taskListStrikethrough
            self.taskListIndentation = taskListIndentation
            self.taskListSpacing = taskListSpacing
        }
    }

    public struct TableConfig {
        public let headerFont: UIFont
        public let cellFont: UIFont
        public let headerTextColor: UIColor
        public let cellTextColor: UIColor
        public let headerBackgroundColor: UIColor
        public let cellBackgroundColor: UIColor
        public let stripedCellBackgroundColor: UIColor
        public let borderColor: UIColor
        public let borderWidth: CGFloat
        public let cornerRadius: CGFloat
        public let cellPadding: UIEdgeInsets
        
        public init(
            headerFont: UIFont = .boldSystemFont(ofSize: 16),
            cellFont: UIFont = .systemFont(ofSize: 16),
            headerTextColor: UIColor = .label,
            cellTextColor: UIColor = .label,
            headerBackgroundColor: UIColor = .systemGray5,
            cellBackgroundColor: UIColor = .systemBackground,
            stripedCellBackgroundColor: UIColor = .systemGray6,
            borderColor: UIColor = .separator,
            borderWidth: CGFloat = 1,
            cornerRadius: CGFloat = 8,
            cellPadding: UIEdgeInsets = UIEdgeInsets(top: 8, left: 12, bottom: 8, right: 12)
        ) {
            self.headerFont = headerFont
            self.cellFont = cellFont
            self.headerTextColor = headerTextColor
            self.cellTextColor = cellTextColor
            self.headerBackgroundColor = headerBackgroundColor
            self.cellBackgroundColor = cellBackgroundColor
            self.stripedCellBackgroundColor = stripedCellBackgroundColor
            self.borderColor = borderColor
            self.borderWidth = borderWidth
            self.cornerRadius = cornerRadius
            self.cellPadding = cellPadding
        }
    }

    public struct ImageConfig {
        public let backgroundColor: UIColor
        public let cornerRadius: CGFloat
        public let maxWidth: CGFloat
        public let placeholderColor: UIColor
        public let loadingIndicatorStyle: UIActivityIndicatorView.Style
        public let titleFont: UIFont
        public let titleColor: UIColor
        
        public init(
            backgroundColor: UIColor = .clear,
            cornerRadius: CGFloat = 8,
            maxWidth: CGFloat = UIScreen.main.bounds.width - 32,
            placeholderColor: UIColor = .systemGray5,
            loadingIndicatorStyle: UIActivityIndicatorView.Style = .medium,
            titleFont: UIFont = .systemFont(ofSize: 14, weight: .regular),
            titleColor: UIColor = .secondaryLabel
        ) {
            self.backgroundColor = backgroundColor
            self.cornerRadius = cornerRadius
            self.maxWidth = maxWidth
            self.placeholderColor = placeholderColor
            self.loadingIndicatorStyle = loadingIndicatorStyle
            self.titleFont = titleFont
            self.titleColor = titleColor
        }
    }

    public struct AlertConfig {
        public let font: UIFont
        public let warningConfig: AlertTypeConfig
        public let errorConfig: AlertTypeConfig
        public let infoConfig: AlertTypeConfig
        public let successConfig: AlertTypeConfig
        public let borderWidth: CGFloat
        public let cornerRadius: CGFloat
        public let padding: UIEdgeInsets
        
        public init(
            font: UIFont = .systemFont(ofSize: 14),
            warningConfig: AlertTypeConfig = AlertTypeConfig(
                backgroundColor: .systemYellow.withAlphaComponent(0.1),
                textColor: .systemYellow,
                borderColor: .systemYellow.withAlphaComponent(0.3)
            ),
            errorConfig: AlertTypeConfig = AlertTypeConfig(
                backgroundColor: .systemRed.withAlphaComponent(0.1),
                textColor: .systemRed,
                borderColor: .systemRed.withAlphaComponent(0.3)
            ),
            infoConfig: AlertTypeConfig = AlertTypeConfig(
                backgroundColor: .systemBlue.withAlphaComponent(0.1),
                textColor: .systemBlue,
                borderColor: .systemBlue.withAlphaComponent(0.3)
            ),
            successConfig: AlertTypeConfig = AlertTypeConfig(
                backgroundColor: .systemGreen.withAlphaComponent(0.1),
                textColor: .systemGreen,
                borderColor: .systemGreen.withAlphaComponent(0.3)
            ),
            borderWidth: CGFloat = 1,
            cornerRadius: CGFloat = 8,
            padding: UIEdgeInsets = UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16)
        ) {
            self.font = font
            self.warningConfig = warningConfig
            self.errorConfig = errorConfig
            self.infoConfig = infoConfig
            self.successConfig = successConfig
            self.borderWidth = borderWidth
            self.cornerRadius = cornerRadius
            self.padding = padding
        }
    }

    public struct AlertTypeConfig {
        public let backgroundColor: UIColor
        public let textColor: UIColor
        public let borderColor: UIColor
        
        public init(
            backgroundColor: UIColor,
            textColor: UIColor,
            borderColor: UIColor
        ) {
            self.backgroundColor = backgroundColor
            self.textColor = textColor
            self.borderColor = borderColor
        }
    }

    public struct ParagraphConfig {
        public let font: UIFont
        public let textColor: UIColor
        public let backgroundColor: UIColor
        public let lineSpacing: CGFloat
        public let paragraphSpacing: CGFloat
        public let alignment: NSTextAlignment
        public let firstLineHeadIndent: CGFloat
        public let headIndent: CGFloat
        public let tailIndent: CGFloat
        public let insets: UIEdgeInsets
        public let lineHeightMultiple: CGFloat
        
        public init(
            font: UIFont = .systemFont(ofSize: 16),
            textColor: UIColor = .label,
            backgroundColor: UIColor = .clear,
            lineSpacing: CGFloat = 4,
            paragraphSpacing: CGFloat = 12,
            alignment: NSTextAlignment = .natural,
            firstLineHeadIndent: CGFloat = 0,
            headIndent: CGFloat = 0,
            tailIndent: CGFloat = 0,
            insets: UIEdgeInsets = UIEdgeInsets(top: 8, left: 0, bottom: 8, right: 0),
            lineHeightMultiple: CGFloat = 1.2
        ) {
            self.font = font
            self.textColor = textColor
            self.backgroundColor = backgroundColor
            self.lineSpacing = lineSpacing
            self.paragraphSpacing = paragraphSpacing
            self.alignment = alignment
            self.firstLineHeadIndent = firstLineHeadIndent
            self.headIndent = headIndent
            self.tailIndent = tailIndent
            self.insets = insets
            self.lineHeightMultiple = lineHeightMultiple
        }
    }
}

public struct MarkdownTheme {
    public let base: BaseConfig
    public let text: TextConfig
    public let heading: HeadingConfig
    public let code: CodeConfig
    public let quote: QuoteConfig
    public let link: LinkConfig
    public let list: ListConfig
    public let table: TableConfig
    public let image: ImageConfig
    public let alert: AlertConfig
    public let paragraph: ParagraphConfig
    
    public init(
        base: BaseConfig = BaseConfig(),
        text: TextConfig = TextConfig(),
        heading: HeadingConfig = HeadingConfig(),
        code: CodeConfig = CodeConfig(),
        quote: QuoteConfig = QuoteConfig(),
        link: LinkConfig = LinkConfig(),
        list: ListConfig = ListConfig(),
        table: TableConfig = TableConfig(),
        image: ImageConfig = ImageConfig(),
        alert: AlertConfig = AlertConfig(),
        paragraph: ParagraphConfig = ParagraphConfig()
    ) {
        self.base = base
        self.text = text
        self.heading = heading
        self.code = code
        self.quote = quote
        self.link = link
        self.list = list
        self.table = table
        self.image = image
        self.alert = alert
        self.paragraph = paragraph
    }
    
    public static let light = MarkdownTheme(
        base: BaseConfig(),
        text: TextConfig(),
        heading: HeadingConfig(),
        code: CodeConfig(),
        quote: QuoteConfig(),
        link: LinkConfig(),
        list: ListConfig(
            font: .systemFont(ofSize: 16),
            textColor: .label,
            backgroundColor: .clear,
            bulletColor: .label,
            bulletFont: .systemFont(ofSize: 16),
            indentationWidth: 20,
            bulletWidth: 20,
            lineSpacing: 4,
            itemSpacing: 8,
            taskListCheckboxSize: 22,
            taskListCheckboxTintColor: .systemBlue,
            taskListTextColor: .label,
            taskListCompletedTextColor: .secondaryLabel,
            taskListStrikethrough: true,
            taskListIndentation: 8,
            taskListSpacing: 12
        ),
        table: TableConfig(),
        image: ImageConfig(
            placeholderColor: .systemGray6,
            titleFont: .systemFont(ofSize: 14, weight: .regular),
            titleColor: .secondaryLabel
        ),
        alert: AlertConfig(),
        paragraph: ParagraphConfig()
    )
    
    public static let dark = MarkdownTheme(
        base: BaseConfig(
            textColor: .white,
            backgroundColor: .black,
            separatorColor: .darkGray
        ),
        text: TextConfig(
            textColor: .white,
            backgroundColor: .clear
        ),
        heading: HeadingConfig.dark,
        code: CodeConfig(
            textColor: .systemPink,
            backgroundColor: .systemGray5,
            inlineTextColor: .systemPink,
            inlineBackgroundColor: .systemGray5,
            borderColor: .darkGray
        ),
        quote: QuoteConfig(
            textColor: .lightGray,
            backgroundColor: .systemGray5,
            borderColor: .systemBlue
        ),
        link: LinkConfig(
            defaultColors: .darkDefault,
            externalColors: .darkExternal,
            internalColors: .darkInternal,
            customColors: .darkCustom
        ),
        list: ListConfig(
            font: .systemFont(ofSize: 16),
            textColor: .white,
            backgroundColor: .clear,
            bulletColor: .white,
            bulletFont: .systemFont(ofSize: 16),
            indentationWidth: 20,
            bulletWidth: 20,
            lineSpacing: 4,
            itemSpacing: 8,
            taskListCheckboxSize: 22,
            taskListCheckboxTintColor: .systemBlue,
            taskListTextColor: .white,
            taskListCompletedTextColor: .gray,
            taskListStrikethrough: true,
            taskListIndentation: 8,
            taskListSpacing: 12
        ),
        table: TableConfig(
            headerTextColor: .white,
            cellTextColor: .white,
            headerBackgroundColor: .systemGray5,
            cellBackgroundColor: .black,
            stripedCellBackgroundColor: .systemGray6.withAlphaComponent(0.3),
            borderColor: .darkGray
        ),
        image: ImageConfig(
            placeholderColor: .systemGray6
        ),
        alert: AlertConfig(),
        paragraph: ParagraphConfig(
            textColor: .white,
            backgroundColor: .clear
        )
    )
}
